#include <windows.h>
#include "..\include\imp_typedefine.h"
#include "..\include\imp_io_wrapper.h"
#include "..\include\imp_mm_wrapper.h"

static HWAVEOUT m_hwo = 0;
static WAVEFORMATEX  m_wfx;
static WAVEHDR m_wdr[2];
static void *	m_wavInst = 0;

static void ime_displ_waveout_init(int ch, int fs, int sb);
static void ime_displ_waveout_deinit(void);

static impmm_sound_func g_wave_func = 0;

static void CALLBACK ime_displ_waveout_proc(
  HWAVEOUT hwo,
  UINT uMsg,
  DWORD dwInstance,
  DWORD dwParam1,
  DWORD dwParam2)
{
	if(uMsg==WOM_DONE)
	{
		int index = 0;
		for(int i=0; i<2; i++)
		{
			if(&(m_wdr[i]) == (WAVEHDR*)dwParam1)
			{
				index = i;
				break;
			}
		}
		if(g_wave_func)
			g_wave_func((Int32)m_wavInst, Ext_AudioPlayDone, index);
	}
	return;
}

static void ime_displ_waveout_init(int ch, int fs, int sb)
{
	HRESULT hr;
	m_wfx.wFormatTag = WAVE_FORMAT_PCM;
	m_wfx.nChannels = ch;
	m_wfx.nSamplesPerSec = fs;
	m_wfx.wBitsPerSample = sb;
	m_wfx.cbSize = 0;
	m_wfx.nAvgBytesPerSec = fs*sb/8;
	m_wfx.nBlockAlign = 1;

	hr = waveOutOpen(&m_hwo, WAVE_MAPPER, &m_wfx, (DWORD)ime_displ_waveout_proc, 0, CALLBACK_FUNCTION);

	if(hr!=S_OK)
		m_hwo = 0;
	m_wdr[0].lpData = 0;
	m_wdr[1].lpData = 0;
}

static void ime_displ_waveout_deinit(void)
{
	if(m_hwo)
	{
		waveOutClose(m_hwo);
		if(m_wdr[0].lpData)
			waveOutUnprepareHeader(m_hwo,  &m_wdr[0], sizeof(m_wdr[0]));
		if(m_wdr[1].lpData)
			waveOutUnprepareHeader(m_hwo,  &m_wdr[1], sizeof(m_wdr[1]));
	}
	m_hwo = 0;
}

void impmm_sound_initialize(impmm_sound_func func)
{
	g_wave_func = func;
	ime_displ_waveout_init(1, 8000, 16);
}

void impmm_sound_deinitialize(void)
{
	ime_displ_waveout_deinit();
	g_wave_func = 0;
}

void impmm_sound_play(void *instance, void * pBuffer, Int32 size, Int32 pts)
{
	m_wavInst = instance;
	if(m_wdr[0].lpData==0)
	{
		m_wdr[0].dwBufferLength = size;
		m_wdr[0].dwBytesRecorded = 0;
		m_wdr[0].dwFlags = 0;
		m_wdr[0].dwLoops = 1;
		m_wdr[0].dwUser = 0;
		m_wdr[0].lpData = (char *)pBuffer;
		m_wdr[0].lpNext = 0;
		MMRESULT mhr = waveOutPrepareHeader(m_hwo,  &m_wdr[0], sizeof(m_wdr[0]));
	}else if(m_wdr[1].lpData==0 && m_wdr[0].lpData!=pBuffer)
	{
		m_wdr[1].dwBufferLength = size;
		m_wdr[1].dwBytesRecorded = 0;
		m_wdr[1].dwFlags = 0;
		m_wdr[1].dwLoops = 1;
		m_wdr[1].dwUser = 0;
		m_wdr[1].lpData = (char *)pBuffer;
		m_wdr[1].lpNext = 0;
		MMRESULT mhr = waveOutPrepareHeader(m_hwo,  &m_wdr[1], sizeof(m_wdr[1]));
	}
	int index = 0;
	for(int i=0; i<2; i++)
	{
		if(m_wdr[i].lpData == pBuffer)
		{
			index = i;
			break;
		}
	}
	waveOutWrite(m_hwo, &m_wdr[index], sizeof(m_wdr[index]));
}

